package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
	"unsafe"
)

// main
//
//	@Description: 获取等待者的数量等指标
func main() {
	test()
}

func test() {
	var wg sync.WaitGroup
	var m Mutex
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			m.Lock()
			time.Sleep(time.Millisecond * 100)
			m.Unlock()
		}()
	}
	count := m.Count()
	fmt.Println("等待者数量count=", count)
	wg.Wait()
	fmt.Println("over")

}

const (
	mutexLocked = 1 << iota // mutex is locked
	mutexWoken
	mutexStarving
	mutexWaiterShift = iota
)

type Mutex struct {
	sync.Mutex
}

// Count
//
//	@Description: 通过state字段，获取等待者数量（重点state复合字段）
//	@receiver m
//	@return int
func (m *Mutex) Count() int {
	// 获取state字段的值
	v := atomic.LoadInt32((*int32)(unsafe.Pointer(&m.Mutex)))
	//右移三位（这里的常量 mutexWaiterShift 的值为 3），就得到了当前等待者的数量。
	//如果当前的锁已经被其他 goroutine 持有，那么，我们就稍微调整一下这个值，加上一个 1
	v = v>>mutexWaiterShift + (v & mutexLocked)
	return int(v)
}
